#include "StdAfx.h"
#include "UIImage.h"
#include "UIImageSource.h"

namespace DirectUI
{
	UI_BEGIN_INTERFACE_MAP(CUIImage, CUIElement)
		UI_INTERFACE_PART(CUIImage, IUIImage, Image)
	UI_END_INTERFACE_MAP()

	CUIImage::CUIImage(void)
	{
		m_spImageSource = new CUIImageSource();
	}

	CUIImage::~CUIImage(void)
	{
	}

	void CUIImage::OnParseAttribute( xml_attribute& attr )
	{
		__super::OnParseAttribute(attr);
	}

	void CUIImage::ParseAttribute( LPCTSTR lpszAttr )
	{
		if ( m_spImageSource )
			m_spImageSource->ParseAttributes(lpszAttr);

		__super::ParseAttribute(lpszAttr);
	}



	void CUIImage::OnDraw( HDC hDC, IUIRender* lpRender )
	{
		__super::OnDraw(hDC, lpRender);

		CUIObjectQIPtr<IUIElement> spElement(this);
		if ( spElement )
		{
			CSize sizeImage = lpRender->GetImageSize(m_spImageSource);
			CRect rcValidArea = m_spImageSource->GetValidImageArea();
			if ( !rcValidArea.IsRectEmpty() )
			{
				sizeImage.cx = min(sizeImage.cx, rcValidArea.Width());
				sizeImage.cy = min(sizeImage.cy, rcValidArea.Height());
			}
		
			CRect rcDraw = spElement->GetRectOffsetTopPage();
			UIImageStretchMode mode = (UIImageStretchMode)GetProperty(Stretch)->GetIntValue();
			switch (mode)
			{
			case DirectUI::UIImageStretchMode::UIImageStretch_None:
				{
					CRect rc = rcDraw;
					rc.left += (rcDraw.Width()-sizeImage.cx)/2;
					rc.right = rc.left + sizeImage.cx;
					rc.top += (rcDraw.Height()-sizeImage.cy)/2;
					rc.bottom = rc.top + sizeImage.cy;
					DrawAlignImage(lpRender, hDC, rc);
				}
				break;
			case DirectUI::UIImageStretchMode::UIImageStretch_Uniform:
				{
					int nxWidth = rcDraw.Height()*sizeImage.cx/sizeImage.cy;
					int nxHeight = rcDraw.Width()*sizeImage.cy/sizeImage.cx;
					if (  nxWidth < rcDraw.Width() )
					{
						assert(nxHeight >= rcDraw.Height());
						CRect rc = rcDraw;
						rc.left += (rcDraw.Width()-nxWidth)/2;
						rc.right = rc.left + nxWidth;
						DrawAlignImage(lpRender, hDC, rc);
					}
					else
					{
						assert(nxWidth >= rcDraw.Width());
						CRect rc = rcDraw;
						rc.top += (rcDraw.Height()-nxHeight)/2;
						rc.bottom = rc.top + nxHeight;
						DrawAlignImage(lpRender, hDC, rc);
					}
				}
				break;
			case DirectUI::UIImageStretchMode::UIImageStretch_UniformToFill:
				{
					CDCHandle dc(hDC);
					CRgn rgn, rgnOld;
					rgn.CreateRectRgn(rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom);
					dc.GetClipRgn(rgnOld);
					dc.SelectClipRgn(rgn);

					int nxWidth = rcDraw.Height()*sizeImage.cx/sizeImage.cy;
					int nxHeight = rcDraw.Width()*sizeImage.cy/sizeImage.cx;
					if (  nxWidth < rcDraw.Width() )
					{
						assert(nxHeight >= rcDraw.Height());
						CRect rc = rcDraw;
						rc.top += (rcDraw.Height()-nxHeight)/2;
						rc.bottom = rc.top + nxHeight;
						DrawAlignImage(lpRender, hDC, rc);
					}
					else
					{
						assert(nxWidth >= rcDraw.Width());
						CRect rc = rcDraw;
						rc.left += (rcDraw.Width()-nxWidth)/2;
						rc.right = rc.left + nxWidth;
						DrawAlignImage(lpRender, hDC, rc);
					}

					dc.SelectClipRgn(rgnOld);
				}
				break;
				break;
			case DirectUI::UIImageStretchMode::UIImageStretch_Fill:
				DrawAlignImage(lpRender, hDC, rcDraw);
				break;
			default:
				break;
			}
		}
	}

	void CUIImage::DrawAlignImage( IUIRender* lpRender, HDC hDC, CRect rc )
	{
		assert(lpRender!=NULL);

		CRect rcAdjust = rc;
		switch ( GetProperty(AlignmentX)->GetAlignValue() )
		{
		case UIAlign_Near:
			rcAdjust.OffsetRect(m_rcElement.left-rcAdjust.left, 0);
			break;

		case UIAlign_Far:
			rcAdjust.OffsetRect(m_rcElement.right-rcAdjust.right, 0);
			break;

		default:
			break;
		}

		switch ( GetProperty(AlignmentY)->GetAlignValue() )
		{
		case UIAlign_Near:
			rcAdjust.OffsetRect(0, m_rcElement.top-rcAdjust.top);
			break;

		case UIAlign_Far:
			rcAdjust.OffsetRect(0, m_rcElement.bottom-rcAdjust.bottom);
			break;

		default:
			break;
		}

		lpRender->DrawImage(hDC, m_spImageSource, rcAdjust);
	}

};
